#ifndef QUERYRESULT_H__
#define QUERYRESULT_H__

#include <vector>
#include <stdlib.h>
#include "define.h"

namespace engine
{
	class DataField
	{
	public:
		enum DataTypes
		{
			DB_TYPE_UNKNOWN = 0x00,
			DB_TYPE_STRING  = 0x01,
			DB_TYPE_INTEGER = 0x02,
			DB_TYPE_FLOAT   = 0x03,
			DB_TYPE_BOOL    = 0x04
		};

		DataField();
		DataField(DataField &f);
		DataField(const char *value, enum DataTypes type);

		~DataField();

		enum DataTypes getType() const
		{
			return mType;
		}

		bool isNULL() const
		{
			return mValue == NULL;
		}

		const char *getString() const
		{
			return mValue;
		}

		const char *getStringSafe() const
		{
			return mValue ? mValue : "";
		}

		float getFloat() const
		{
			return mValue ? static_cast<float>(atof(mValue)) : 0.0f;
		}

		bool getBool() const
		{
			return mValue ? atoi(mValue) > 0 : false;
		}

		int32 getInt32() const
		{
			return mValue ? static_cast<int32>(atol(mValue)) : int32(0);
		}

		uint8 getUInt8() const
		{
			return mValue ? static_cast<uint8>(atol(mValue)) : uint8(0);
		}

		uint16 getUInt16() const
		{
			return mValue ? static_cast<uint16>(atol(mValue)) : uint16(0);
		}

		int16 getInt16() const
		{
			return mValue ? static_cast<int16>(atol(mValue)) : int16(0);
		}

		uint32 getUInt32() const
		{
			return mValue ? static_cast<uint32>(strtoul(mValue, NULL, 10)) : uint32(0);
		}

		void setType(enum DataTypes type)
		{
			mType = type;
		}

		void setValue(const char *value);

	private:
		char *mValue;
		enum DataTypes mType;
	};

	class QueryResult
	{
	public:
		QueryResult(uint32 rowCount, uint32 fieldCount)
			: mFieldCount(fieldCount), mRowCount(rowCount) {}

		virtual ~QueryResult() {}

		virtual bool nextRow() = 0;

		DataField *fetch() const
		{
			return mCurrentRow;
		}

		const DataField & operator [] (int index) const
		{
			return mCurrentRow[index];
		}

		uint32 getFieldCount() const
		{
			return mFieldCount;
		}
		uint32 getRowCount() const
		{
			return mRowCount;
		}

	protected:
		DataField *mCurrentRow;
		uint32 mFieldCount;
		uint32 mRowCount;
	};

	class QueryResultSet
	{
	public:
		~QueryResultSet()
		{
			for (size_t i = 0; i < mResults.size(); i++)
			{
				delete mResults[i];
			}

			mResults.clear();
		}

		QueryResult* getResult(size_t index)
		{
			if (index >= mResults.size())
			{
				return NULL;
			}

			return mResults[index];
		}

		void pushResult(QueryResult *result)
		{
			mResults.push_back(result);
		}

		size_t getCount()
		{
			return mResults.size();
		}

	protected:
		std::vector<QueryResult*> mResults;
	};

}

#endif
